#include "AES.h"

const unsigned char Sbox[16][16] = {
    0x63,   0x7c,   0x77,   0x7b,   0xf2,   0x6b,   0x6f,   0xc5,   0x30,   0x01,   0x67,   0x2b,   0xfe,   0xd7,   0xab,   0x76,
    0xca,   0x82,   0xc9,   0x7d,   0xfa,   0x59,   0x47,   0xf0,   0xad,   0xd4,   0xa2,   0xaf,   0x9c,   0xa4,   0x72,   0xc0,
    0xb7,   0xfd,   0x93,   0x26,   0x36,   0x3f,   0xf7,   0xcc,   0x34,   0xa5,   0xe5,   0xf1,   0x71,   0xd8,   0x31,   0x15,
    0x04,   0xc7,   0x23,   0xc3,   0x18,   0x96,   0x05,   0x9a,   0x07,   0x12,   0x80,   0xe2,   0xeb,   0x27,   0xb2,   0x75,
    0x09,   0x83,   0x2c,   0x1a,   0x1b,   0x6e,   0x5a,   0xa0,   0x52,   0x3b,   0xd6,   0xb3,   0x29,   0xe3,   0x2f,   0x84,
    0x53,   0xd1,   0x00,   0xed,   0x20,   0xfc,   0xb1,   0x5b,   0x6a,   0xcb,   0xbe,   0x39,   0x4a,   0x4c,   0x58,   0xcf,
    0xd0,   0xef,   0xaa,   0xfb,   0x43,   0x4d,   0x33,   0x85,   0x45,   0xf9,   0x02,   0x7f,   0x50,   0x3c,   0x9f,   0xa8,
    0x51,   0xa3,   0x40,   0x8f,   0x92,   0x9d,   0x38,   0xf5,   0xbc,   0xb6,   0xda,   0x21,   0x10,   0xff,   0xf3,   0xd2,
    0xcd,   0x0c,   0x13,   0xec,   0x5f,   0x97,   0x44,   0x17,   0xc4,   0xa7,   0x7e,   0x3d,   0x64,   0x5d,   0x19,   0x73,
    0x60,   0x81,   0x4f,   0xdc,   0x22,   0x2a,   0x90,   0x88,   0x46,   0xee,   0xb8,   0x14,   0xde,   0x5e,   0x0b,   0xdb,
    0xe0,   0x32,   0x3a,   0x0a,   0x49,   0x06,   0x24,   0x5c,   0xc2,   0xd3,   0xac,   0x62,   0x91,   0x95,   0xe4,   0x79,
    0xe7,   0xc8,   0x37,   0x6d,   0x8d,   0xd5,   0x4e,   0xa9,   0x6c,   0x56,   0xf4,   0xea,   0x65,   0x7a,   0xae,   0x08,
    0xba,   0x78,   0x25,   0x2e,   0x1c,   0xa6,   0xb4,   0xc6,   0xe8,   0xdd,   0x74,   0x1f,   0x4b,   0xbd,   0x8b,   0x8a,
    0x70,   0x3e,   0xb5,   0x66,   0x48,   0x03,   0xf6,   0x0e,   0x61,   0x35,   0x57,   0xb9,   0x86,   0xc1,   0x1d,   0x9e,
    0xe1,   0xf8,   0x98,   0x11,   0x69,   0xd9,   0x8e,   0x94,   0x9b,   0x1e,   0x87,   0xe9,   0xce,   0x55,   0x28,   0xdf,
    0x8c,   0xa1,   0x89,   0x0d,   0xbf,   0xe6,   0x42,   0x68,   0x41,   0x99,   0x2d,   0x0f,   0xb0,   0x54,   0xbb,   0x16
};

const unsigned char SNbox[16][16] = {
    0x52,   0x09,   0x6a,   0xd5,   0x30,   0x36,   0xa5,   0x38,   0xbf,   0x40,   0xa3,   0x9e,   0x81,   0xf3,   0xd7,   0xfb,
    0x7c,   0xe3,   0x39,   0x82,   0x9b,   0x2f,   0xff,   0x87,   0x34,   0x8e,   0x43,   0x44,   0xc4,   0xde,   0xe9,   0xcb,
    0x54,   0x7b,   0x94,   0x32,   0xa6,   0xc2,   0x23,   0x3d,   0xee,   0x4c,   0x95,   0x0b,   0x42,   0xfa,   0xc3,   0x4e,
    0x08,   0x2e,   0xa1,   0x66,   0x28,   0xd9,   0x24,   0xb2,   0x76,   0x5b,   0xa2,   0x49,   0x6d,   0x8b,   0xd1,   0x25,
    0x72,   0xf8,   0xf6,   0x64,   0x86,   0x68,   0x98,   0x16,   0xd4,   0xa4,   0x5c,   0xcc,   0x5d,   0x65,   0xb6,   0x92,
    0x6c,   0x70,   0x48,   0x50,   0xfd,   0xed,   0xb9,   0xda,   0x5e,   0x15,   0x46,   0x57,   0xa7,   0x8d,   0x9d,   0x84,
    0x90,   0xd8,   0xab,   0x00,   0x8c,   0xbc,   0xd3,   0x0a,   0xf7,   0xe4,   0x58,   0x05,   0xb8,   0xb3,   0x45,   0x06,
    0xd0,   0x2c,   0x1e,   0x8f,   0xca,   0x3f,   0x0f,   0x02,   0xc1,   0xaf,   0xbd,   0x03,   0x01,   0x13,   0x8a,   0x6b,
    0x3a,   0x91,   0x11,   0x41,   0x4f,   0x67,   0xdc,   0xea,   0x97,   0xf2,   0xcf,   0xce,   0xf0,   0xb4,   0xe6,   0x73,
    0x96,   0xac,   0x74,   0x22,   0xe7,   0xad,   0x35,   0x85,   0xe2,   0xf9,   0x37,   0xe8,   0x1c,   0x75,   0xdf,   0x6e,
    0x47,   0xf1,   0x1a,   0x71,   0x1d,   0x29,   0xc5,   0x89,   0x6f,   0xb7,   0x62,   0x0e,   0xaa,   0x18,   0xbe,   0x1b,
    0xfc,   0x56,   0x3e,   0x4b,   0xc6,   0xd2,   0x79,   0x20,   0x9a,   0xdb,   0xc0,   0xfe,   0x78,   0xcd,   0x5a,   0xf4,
    0x1f,   0xdd,   0xa8,   0x33,   0x88,   0x07,   0xc7,   0x31,   0xb1,   0x12,   0x10,   0x59,   0x27,   0x80,   0xec,   0x5f,
    0x60,   0x51,   0x7f,   0xa9,   0x19,   0xb5,   0x4a,   0x0d,   0x2d,   0xe5,   0x7a,   0x9f,   0x93,   0xc9,   0x9c,   0xef,
    0xa0,   0xe0,   0x3b,   0x4d,   0xae,   0x2a,   0xf5,   0xb0,   0xc8,   0xeb,   0xbb,   0x3c,   0x83,   0x53,   0x99,   0x61,
    0x17,   0x2b,   0x04,   0x7e,   0xba,   0x77,   0xd6,   0x26,   0xe1,   0x69,   0x14,   0x63,   0x55,   0x21,   0x0c,   0x7d
};

const unsigned char Rcon[10] = {
    0x01,   0x02,   0x04,   0x08,   0x10,   0x20,   0x40,   0x80,   0x1B,   0x36
}

#define KEYEXP_BUF_SDRAM_ADDR_START_H     0x01
#define KEYEXP_BUF_SDRAM_ADDR_START_L     0x00
#define KEYEXP_W00_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x00)
#define KEYEXP_W01_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x01)
#define KEYEXP_W02_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x02)
#define KEYEXP_W03_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x03)
#define KEYEXP_W10_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x04)
#define KEYEXP_W11_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x05)
#define KEYEXP_W12_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x06)
#define KEYEXP_W13_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x07)
#define KEYEXP_W20_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x08)
#define KEYEXP_W21_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x09)
#define KEYEXP_W22_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0A)
#define KEYEXP_W23_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0B)
#define KEYEXP_W30_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0C)
#define KEYEXP_W31_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0D)
#define KEYEXP_W32_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0E)
#define KEYEXP_W33_SDRAM_ADDR_L           (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x0F)

#define BUFFER_TMP_SDRAM_ADDR_START_H     0x01
#define BUFFER_TMP_SDRAM_ADDR_START_L     (KEYEXP_BUF_SDRAM_ADDR_START_L + 0x10)

#define SRC_DATA_SDRAM_ADDR_START_H       0x01
#define SRC_DATA_SDRAM_ADDR_START_L       (BUFFER_TMP_SDRAM_ADDR_START_L + 0x10)


static unsigned char xdata KeyExp_w00 _at_ KEYEXP_W00_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w01 _at_ KEYEXP_W01_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w02 _at_ KEYEXP_W02_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w03 _at_ KEYEXP_W03_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w10 _at_ KEYEXP_W10_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w11 _at_ KEYEXP_W11_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w12 _at_ KEYEXP_W12_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w13 _at_ KEYEXP_W13_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w20 _at_ KEYEXP_W20_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w21 _at_ KEYEXP_W21_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w22 _at_ KEYEXP_W22_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w23 _at_ KEYEXP_W23_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w30 _at_ KEYEXP_W30_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w31 _at_ KEYEXP_W31_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w32 _at_ KEYEXP_W32_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥
static unsigned char xdata KeyExp_w33 _at_ KEYEXP_W33_SDRAM_ADDR_L ;// 轮秘钥计算完成后存储该轮轮秘钥

static unsigned char xdata buffer_tmp[4][4] _at_ BUFFER_TMP_SDRAM_ADDR_START_L ;
unsigned char xdata sbuf[4][4] _at_ SRC_DATA_SDRAM_ADDR_START_L;


// void AES_SHIFT(unsigned char start_addrh,unsigned char start_addrl,unsigned char length,unsigned char type);
void AES_XOR(unsigned char src_addrh,unsigned char src_addrl,unsigned char add_addrh,unsigned char add_addrl,unsigned char length)
{
    unsigned char xdata *srcp;
    unsigned char xdata *addp;
    unsigned char xdata  i   ;
    srcp = unsigned int (src_addrl) ;
    addp = unsigned int (add_addrl) ;
    for(i=0;i<length;i++){
        *(srcp+i) = *(srcp+i) ^ *(addp+i);
    }
}


unsigned char S_Transform( unsigned char inputdata)
{
    return Sbox[inputdata>>4][inputdata&0x0f];
}
unsigned char SN_Transform( unsigned char inputdata)
{
    return SNbox[inputdata>>4][inputdata&0x0f];
}

void AES_KeyRound(unsigned char step){

    unsigned char xdata i,j;

    //------------- i等于4的整倍数时 需要进行一次8bit移位且S盒变换
    // 1.将W3备份到W4,并移位：W[4][3]、W[3][2]、W[2][1]、W[1][0]  ->   W[4][2]、W[4][1]、W[4][0]、W[4][3]
    buffer_tmp[0][0] = KeyExp_w33;
    buffer_tmp[0][1] = KeyExp_w30;
    buffer_tmp[0][2] = KeyExp_w31;
    buffer_tmp[0][3] = KeyExp_w32;

    // 2.分别将W[3]放入S盒进行变换
    buffer_tmp[0][0] = S_Transform(buffer_tmp[0][0]);
    buffer_tmp[0][1] = S_Transform(buffer_tmp[0][1]);
    buffer_tmp[0][2] = S_Transform(buffer_tmp[0][2]);
    buffer_tmp[0][3] = S_Transform(buffer_tmp[0][3]);

    // 3.将w[3]与轮常量Rcon进行异或
    buffer_tmp[0][3] = buffer_tmp[0][3] ^ Rcon[step];

    //------------- 计算 W[i] 的值
    for(i = 0 ; i < 4 ;i++) {
        j = (i==0) ? 4 : (i-1) ;
        // 4.将w[i]与W[i-1]相异或,新的值存在W[i]内
        AES_XOR(KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_W00_SDRAM_ADDR_L+i,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_W00_SDRAM_ADDR_L+j,32);
    }
    // 执行结束后，W3 W2 W1 W0 中放的就是轮秘钥
}



unsigned char AES_LineMul(unsigned char data,unsigned char mul)
{
    unsigned char i;
    unsigned char buf = 0;

    for(i=0;i<(mul>>1);i++){
        if(data&0x80) buf = data ^ 0x1B;
        else          buf = data << 1  ;
    }
    if(mul & 0x01) buf = buf ^ data;
}


// 加密算法流程
void AES_Encryption(unsigned char* sdata_start_addr,unsigned char block_max)
{
    unsigned char xdata i,j;
    unsigned char xdata block_cnt,round_cnt;

    for(block_cnt = 0; block_cnt < block_max ; block_cnt++){

        // 1. 明文填充，默认大端存储
        for(i = 0 ; i < 16 ;i++){
            // CBC模式，和上一个block值进行异或
            *((&sbuf[0][0]) + i) = (*(sdata_start_addr +(block_cnt<<4)+ i)) ^ *((&sbuf[0][0]) + i);
        }

        // 2. 秘钥填充
        for(i = 0 ; i < 16 ;i++){
            *((&KeyExp_w00) + i) = *(key_start_addr + i);
        }

        // 3.轮秘钥加
        AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,32);

        // 4.执行10次轮函数
        for(round_cnt = 0 ; round_cnt < 10 ; round_cnt++) {

            // 4.1 获取该轮轮秘钥
            AES_KeyRound(round_cnt);

            // 4.2 行移位操作 可优化项
            buffer_tmp[0][3] = sbuf[0][1]; sbuf[0][1] = sbuf[1][1] ; sbuf[1][1] = sbuf[2][1]       ; sbuf[2][1]      = buffer_tmp[0][3];
            buffer_tmp[0][3] = sbuf[3][3]; sbuf[3][3] = sbuf[2][3] ; sbuf[2][3] = sbuf[1][3]       ; sbuf[1][3]      = buffer_tmp[0][3];
            buffer_tmp[0][3] = sbuf[0][2]; sbuf[0][2] = sbuf[2][2] ; sbuf[2][2] = buffer_tmp[0][3] ;buffer_tmp[0][3] = sbuf[1][2]      ; sbuf[1][2] = sbuf[3][2] ; sbuf[3][2] = buffer_tmp[0][3];

            // 4.3 列混合操作
            for(i = 0; i < 4 ;i++){

                if(round_cnt == 9) break; // 最后一个周期不执行列混合

                for(j = 0 ; j < 4 ;j++){
                    switch(i){
                        case 0: {
                            buffer_tmp[0][j] = AES_LineMul(sbuf[0][j],2) ^ AES_LineMul(sbuf[1][j],3) ^ sbuf[2][j] ^ sbuf[3][j];
                            break;
                        }
                        case 1: {
                            buffer_tmp[1][j] = sbuf[0][j] ^ AES_LineMul(sbuf[1][j],2) ^ AES_LineMul(sbuf[2][j],3) ^ sbuf[3][j];
                            break;
                        }
                        case 2: {
                            buffer_tmp[2][j] = sbuf[0][j] ^ sbuf[1][j] ^ AES_LineMul(sbuf[2][j],2) ^ AES_LineMul(sbuf[3][j],3);
                            break;
                        }
                        case 3: {
                            buffer_tmp[0][j] = AES_LineMul(sbuf[0][j],3)  ^ sbuf[1][j] ^ sbuf[2][j] ^ AES_LineMul(sbuf[3][j],2);
                            break;
                        }
                    }
                }
            }

            // 4.4轮秘钥加
            AES_XOR(BUFFER_TMP_SDRAM_ADDR_START_H,BUFFER_TMP_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,32);

            // 4.5.输出轮密文
            for(i = 0 ; i < 16 ;i++){
                *((&sbuf[0][0]) + i) = *((&buffer_tmp[0][0]) + i);
            }
        }

    }
}

// 解密算法流程
void AES_Decryption(unsigned char* sdata_start_addr,unsigned char* key_start_addr,unsigned char block_max)
{
    unsigned char xdata i,j;
    unsigned char xdata block_cnt,round_cnt;

    for(block_cnt = block_max; block_cnt > 0 ; block_cnt --){

        // 1. 密文填充，默认大端存储
        for(i = 0 ; i < 16 ;i++){
            *((&sbuf[0][0]) + i) = *(sdata_start_addr + ((block_cnt-1)<<4) + i);
        }

        // 2. 秘钥填充
        for(i = 0 ; i < 16 ;i++){
            *((&KeyExp_w00) + i) = *(key_start_addr + i);
        }

        // 3.轮秘钥加
        AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,32);

        // 4.执行10次轮函数
        for(round_cnt = 10 ; round_cnt > 0 ; round_cnt--) {

            // 4.1 获取该轮轮秘钥
            for(i=0;i<round_cnt;i++)   AES_KeyRound(i);

            // 4.2 逆行移位操作 可优化项--需要重点检查！！检查完修改注释
            buffer_tmp[0][3] = sbuf[3][1]; sbuf[3][1] = sbuf[2][1] ; sbuf[2][1] = sbuf[1][1]       ; sbuf[1][1]      = buffer_tmp[0][3];
            buffer_tmp[0][3] = sbuf[0][2]; sbuf[0][2] = sbuf[2][2] ; sbuf[2][2] = buffer_tmp[0][3] ;buffer_tmp[0][3] = sbuf[1][2]      ; sbuf[1][2] = sbuf[3][2] ; sbuf[3][2] = buffer_tmp[0][3];
            buffer_tmp[0][3] = sbuf[0][3]; sbuf[0][3] = sbuf[1][3] ; sbuf[1][3] = sbuf[2][3]       ; sbuf[2][3]      = buffer_tmp[0][3];

            // 4.3 逆盒变换
            for(i=0;i<16;i++){
                *(&(sbuf[0][0])+i) = SN_Transform(*(&(sbuf[0][0])+i));
            }

            // 4.4 轮秘钥加
            AES_XOR(SRC_DATA_SDRAM_ADDR_START_H,SRC_DATA_SDRAM_ADDR_START_L,KEYEXP_BUF_SDRAM_ADDR_START_H,KEYEXP_BUF_SDRAM_ADDR_START_L,32);

            // 4.5 逆列混合操作
            for(i = 0; i < 4 ;i++){

                if(round_cnt == 1) break; // 最后一个周期不执行列混合

                for(j = 0 ; j < 4 ;j++){
                    switch(i){
                        case 0: {
                            buffer_tmp[0][j] = AES_LineMul(sbuf[0][j],0x0E) ^ AES_LineMul(sbuf[1][j],0x0B) ^ AES_LineMul(sbuf[2][j],0x0D) ^ AES_LineMul(sbuf[3][j],0x09);
                            break;
                        }
                        case 1: {
                            buffer_tmp[1][j] = AES_LineMul(sbuf[0][j],0x09) ^ AES_LineMul(sbuf[1][j],0x0E) ^ AES_LineMul(sbuf[2][j],0x0B) ^ AES_LineMul(sbuf[3][j],0x0D);
                            break;
                        }
                        case 2: {
                            buffer_tmp[2][j] = AES_LineMul(sbuf[0][j],0x0D) ^ AES_LineMul(sbuf[1][j],0x09) ^ AES_LineMul(sbuf[2][j],0x0E) ^ AES_LineMul(sbuf[3][j],0x0B);
                            break;
                        }
                        case 3: {
                            buffer_tmp[0][j] = AES_LineMul(sbuf[0][j],0x0B)  ^ AES_LineMul(sbuf[1][j],0x0D) ^ AES_LineMul(sbuf[2][j],0x09) ^ AES_LineMul(sbuf[3][j],0x0E);
                            break;
                        }
                    }
                }
            }

            // 4.6 输出轮明文
            for(i = 0 ; i < 16 ;i++){
                *((&sbuf[0][0]) + i) = *((&buffer_tmp[0][0]) + i) ;
            }
        }

    }
}